x86,hvm: Allow delivery of timer interrupts to VCPUs != 0
authorKeir Fraser <keir.fraser@citrix.com>
Tue, 7 Jul 2009 13:21:16 +0000 (14:21 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Tue, 7 Jul 2009 13:21:16 +0000 (14:21 +0100)
This patch is needed for kexec/kdump since VCPU#0 is halted.

Signed-off-by: Kouya Shimura <kouya@jp.fujitsu.com>
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
xen/arch/x86/hvm/hpet.c
xen/arch/x86/hvm/i8254.c
xen/arch/x86/hvm/rtc.c
xen/arch/x86/hvm/vlapic.c
xen/arch/x86/hvm/vpt.c
xen/include/asm-x86/hvm/vpt.h

index 1330a6f6348e7787c08a77bff3fc07b14da2078f..89af0b61eedbb6deeb64dc68c0b2a3ec805485b8 100644 (file)
@@ -28,7 +28,7 @@
 #define vcpu_vhpet(vcpu)   (domain_vhpet((vcpu)->domain))
 #define vhpet_domain(hpet) (container_of((hpet), struct domain, \
                                          arch.hvm_domain.pl_time.vhpet))
-#define vhpet_vcpu(hpet)   (vhpet_domain(hpet)->vcpu[0])
+#define vhpet_vcpu(hpet)   (pt_global_vcpu_target(vhpet_domain(hpet)))
 
 #define HPET_BASE_ADDRESS   0xfed00000ULL
 #define HPET_MMAP_SIZE      1024
index a87ddecc5816206acb7477028ac859e447467798..5394679a8e539cb9577e637b2e3b4f5a04e28a15 100644 (file)
@@ -42,7 +42,7 @@
 #define vcpu_vpit(vcpu)  (domain_vpit((vcpu)->domain))
 #define vpit_domain(pit) (container_of((pit), struct domain, \
                                        arch.hvm_domain.pl_time.vpit))
-#define vpit_vcpu(pit)   (vpit_domain(pit)->vcpu[0])
+#define vpit_vcpu(pit)   (pt_global_vcpu_target(vpit_domain(pit)))
 
 #define RW_STATE_LSB 1
 #define RW_STATE_MSB 2
index 9ab69033b05a55350e6dbab8b92a6656004caef1..0128d02419d99add1441d8047048b7d751c553a4 100644 (file)
@@ -32,7 +32,7 @@
 #define vcpu_vrtc(vcpu)  (domain_vrtc((vcpu)->domain))
 #define vrtc_domain(rtc) (container_of((rtc), struct domain, \
                                        arch.hvm_domain.pl_time.vrtc))
-#define vrtc_vcpu(rtc)   (vrtc_domain(rtc)->vcpu[0])
+#define vrtc_vcpu(rtc)   (pt_global_vcpu_target(vrtc_domain(rtc)))
 
 static void rtc_periodic_cb(struct vcpu *v, void *opaque)
 {
index cfa6ecf95e9b0683c5720c926257a8052ae6eaff..1f42a60591287ae05e6da6a735fd46cb59f519cf 100644 (file)
@@ -814,7 +814,10 @@ void vlapic_adjust_i8259_target(struct domain *d)
     v = d->vcpu ? d->vcpu[0] : NULL;
 
  found:
+    if ( d->arch.hvm_domain.i8259_target == v )
+        return;
     d->arch.hvm_domain.i8259_target = v;
+    pt_adjust_global_vcpu_target(v);
 }
 
 int vlapic_has_pending_irq(struct vcpu *v)
index 6a12d37a2132596bcf8a232180a48a2ed52e4e1d..a949d918ba00653514ba551fe32d70724360a7a9 100644 (file)
@@ -437,3 +437,53 @@ void destroy_periodic_time(struct periodic_time *pt)
      */
     kill_timer(&pt->timer);
 }
+
+static void pt_adjust_vcpu(struct periodic_time *pt, struct vcpu *v)
+{
+    int on_list;
+
+    ASSERT(pt->source == PTSRC_isa);
+
+    if ( pt->vcpu == NULL )
+        return;
+
+    pt_lock(pt);
+    on_list = pt->on_list;
+    if ( pt->on_list )
+        list_del(&pt->list);
+    pt->on_list = 0;
+    pt_unlock(pt);
+
+    spin_lock(&v->arch.hvm_vcpu.tm_lock);
+    pt->vcpu = v;
+    if ( on_list )
+    {
+        pt->on_list = 1;
+        list_add(&pt->list, &v->arch.hvm_vcpu.tm_list);
+
+        migrate_timer(&pt->timer, v->processor);
+    }
+    spin_unlock(&v->arch.hvm_vcpu.tm_lock);
+}
+
+void pt_adjust_global_vcpu_target(struct vcpu *v)
+{
+    struct pl_time *pl_time = &v->domain->arch.hvm_domain.pl_time;
+    int i;
+
+    if ( v == NULL )
+        return;
+
+    spin_lock(&pl_time->vpit.lock);
+    pt_adjust_vcpu(&pl_time->vpit.pt0, v);
+    spin_unlock(&pl_time->vpit.lock);
+
+    spin_lock(&pl_time->vrtc.lock);
+    pt_adjust_vcpu(&pl_time->vrtc.pt, v);
+    spin_unlock(&pl_time->vrtc.lock);
+
+    spin_lock(&pl_time->vhpet.lock);
+    for ( i = 0; i < HPET_TIMER_NUM; i++ )
+        pt_adjust_vcpu(&pl_time->vhpet.pt[i], v);
+    spin_unlock(&pl_time->vhpet.lock);
+}
index 12ce3e4826beff4ddcc8e78fc099e77ff58b4c47..2d572d5376d781d1a204765563383fd0d010c9d9 100644 (file)
@@ -142,6 +142,10 @@ void pt_intr_post(struct vcpu *v, struct hvm_intack intack);
 void pt_reset(struct vcpu *v);
 void pt_migrate(struct vcpu *v);
 
+void pt_adjust_global_vcpu_target(struct vcpu *v);
+#define pt_global_vcpu_target(d) \
+    ((d)->arch.hvm_domain.i8259_target ? : (d)->vcpu ? (d)->vcpu[0] : NULL)
+
 /* Is given periodic timer active? */
 #define pt_active(pt) ((pt)->on_list)